<template>
  <div>
    <u-form-item v-bind="formItemProps" @click="onFormItemClick">
      <template v-slot:right>
        <slot name="right"></slot>
      </template>
      <u--input
        v-bind="formInputProps"
        v-on="formInputEvents"
        v-model="valueComputed"
      ></u--input>
    </u-form-item>
    <u-picker
      v-bind="pickerProps"
      :show="showPicker"
      :keyName="keyName"
      :columns="pickerColumns"
      @close="emit('pickerClose')"
      @change="emit('pickerChange')"
      @confirm="handleConfirm"
      @cancel="handleCancel"
    ></u-picker>
  </div>
</template>

<script>
/**
 * @description: 下拉框组件
 * 继承了 u-form-item 和 u-input 的所有属性和事件 以及 u-form-item 的插槽
 * 可以像原来使用 u-form-item 和 u-input 一样使用
 *
 * @example: 传入 columns 属性
 * <Dropdown
 *   v-model="value"
 *   prop="prop"
 *   refName="refName"
 *   label="label"
 *  :borderBottom="false"
 *  @click="click"
 * />
 * 
 * @example: 传入 api 属性
 * <Dropdown
 *  v-model="value"
 *  :api="api.taskList"
 *  dataKey="result.records"
 * />
 */

const commonProp = ["style", "class"];

export default {
  name: "CDropdown",
  props: {
    value: {
      type: [String, Number],
      default: "",
    },
    keyName: {
      type: String,
      default: "label",
    },
    valName: {
      type: String,
      default: "id",
    },
    api: {
      type: [Promise, Function],
      default: () => {}
    },
    dataKey: {
      type: String,
      default: 'result',
    },
    // 点击取消时的默认值
    cancelValue: {
      type: [String, Number],
      default: "",
    },
  },
  data() {
    return {
      remoteColumns: [],
      showPicker: false,
    };
  },
  computed: {
    valueComputed: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit("input", value);
      },
    },
    /**
     * picker 的 columns
     */
    pickerColumns: {
      get() {
        // 如果传入了 columns 属性则使用传入的
        if (Object.keys(this.$attrs).includes('columns')) {
          return this.$attrs.columns;
        } else {
          return this.remoteColumns;
        }
      },
      set(val) {
        this.remoteColumns = val;
      },
    },
    /**
     * u-form-item 的 props 属性
     */
    formItemProps() {
      const props = [
        "label",
        "prop",
        "borderBottom",
        "labelWidth",
        "labelPosition",
        "rightIcon",
        "leftIcon",
        "leftIconStyle",
        "required",
      ].concat(commonProp);
      return this.filterObjectByKeys(this.$attrs, props);
    },
    /**
     * picker 的 props 属性
     */
    pickerProps() {
      const props = [
        "show",
        "showToolbar",
        "title",
        "columns",
        "loading",
        "itemHeight",
        "cancelText",
        "confirmText",
        "cancelColor",
        "confirmColor",
        "visibleItemCount",
        "keyName",
        "closeOnClickOverlay",
        "defaultIndex",
        "immediateChange",
      ].concat(commonProp);
      return this.filterObjectByKeys(this.$attrs, props);
    },
    /**
     * u-input 的 props 属性
     */
    formInputProps() {
      const props = [
        "value",
        "type",
        "disabled",
        "disabledColor",
        "clearable",
        "password",
        "maxlength",
        "placeholder",
        "placeholderClass",
        "placeholderStyle",
        "showWordLimit",
        "confirmType",
        "confirmHold",
        "holdKeyboard",
        "focus",
        "autoBlur",
        "ignoreCompositionEvent",
        "disableDefaultPadding",
        "cursor",
        "cursorSpacing",
        "selectionStart",
        "selectionEnd",
        "adjustPosition",
        "inputAlign",
        "fontSize",
        "color",
        "prefixIcon",
        "prefixIconStyle",
        "suffixIcon",
        "suffixIconStyle",
        "border",
        "readonly",
        "shape",
        "formatter",
        "customStyle",
      ].concat(commonProp);
      return this.filterObjectByKeys(this.$attrs, props);
    },
    /**
     * u-input 的 event 属性
     */
    formInputEvents() {
      const events = [
        "blur",
        "focus",
        "confirm",
        "keyboardheightchange",
        "input",
        "change",
        "clear",
      ];
      return this.filterObjectByKeys(this.$listeners, events);
    },
  },
  created() {
    if (!!this.api && typeof this.api.then === 'function')  {
      this.api.then(res => {
        const data = this.getObjectByKey(res, this.dataKey);
        this.pickerColumns = data ? [data] : []
      })
    }
  },
  methods: {
    /**
     * 按 key 获取对象的值，可以使用点语法
     * 这个组件里用于获取 axios 的返回值
     * @param {Object} obj
     * @param {String} key
     * @example: getObjectByKey({a: {b: 1}}, 'a.b') => 1
     * @return {Any}
     */
    getObjectByKey(obj, key) {
      return key.split(".").reduce((o, k) => (o || {})[k], obj);
    },
    /**
     * 判断对象中是否包含某个属性
     */
    hasOwnProperty(obj, prop) {
      return Object.keys(obj).includes(prop);
    },
    /**
     * 过滤对象的属性
     * @param {Object} obj
     * @param {Array} keyArr
     * @return {Object}
     */
    filterObjectByKeys(obj, keyArr) {
      const keys = Object.entries(obj);
      const filtered = keys.filter(([key, value]) => keyArr.includes(key));
      return Object.fromEntries(filtered);
    },
    /**
     * 处理点击确定事件
     */
    handleConfirm(e) {
      this.valueComputed = e.value[0][this.valueName];
      this.showPicker = false;
      this.$emit("pickerConfirm");
      this.$emit('update:label', e.value[0][this.keyName])
    },
    /**
     * 处理点击取消事件
     */
    handleCancel() {
      this.showPicker = false;
      this.valueComputed = null;
      this.$emit("pickerCancel");
      this.$emit("update:label", this.cancelValue);
    },
    /**
     * 点击 form-item 事件
     */
    onFormItemClick() {
      this.showPicker = true;
      this.$emit("formItemClick");
    },
  },
};
</script>
